package vesion2.tank;


import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonSetter;
import vesion2.barrier.Barrier;
import vesion2.main.ObjectManager;
import vesion2.object.special.Motion;
import vesion2.object.Point;
import vesion2.object.Rectangle;
import vesion2.object.special.Orientation;
import vesion2.tool.Bomb;
import vesion2.tool.LoadImages;
import vesion2.tool.Timer1;

import java.awt.*;
import java.io.Serializable;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 一种以矩形构建的自定义的基础坦克
 */

public class BaseTank extends Rectangle implements Motion, Serializable {
    protected int ort;

    @JsonIgnore
    protected ObjectManager manager;
    protected int speed;

    @JsonIgnore
    protected ReentrantReadWriteLock rwLock=new ReentrantReadWriteLock();
    //控制子弹射击频率
    protected transient Timer1 timer1;

    @JsonIgnore
    public BaseTank(){this(new Point());};
    /**
     * 默认朝上
     * @param left_up 坦克矩形左上角顶点
     */
    public BaseTank(Point left_up) {
        this(left_up,0);
    }

    /**
     *
     * @param left_up 坦克矩形左上角顶点
     * @param ort 四个方向 上0,下1,左2,右3
     */
    public BaseTank(Point left_up, int ort) {
        this(left_up,ort,null);
    }

    public BaseTank(Point left_up,int ort,ObjectManager manager){
        super(left_up,40,50);
        this.speed=5;
        this.ort=ort;
        this.manager=manager;
        timer1=new Timer1(300);
    }

    public int getSpeed() {
        return speed;
    }

    /**
     *
     * @param speed 平均每100毫秒移动的总像素个数
     */
    public void setSpeed(int speed) {
        this.speed = speed;
    }

    /**
     * 修改最大射击频率
     * @param interTime
     */
    public void setMinInterTime(int interTime){
        timer1.setInterval(interTime);
    }

    public int  getMinInterTime(){
        return timer1.getInterval();
    }

    public int getOrt() {
        return ort;
    }

    public void setOrt(int ort) {
        rwLock.writeLock().lock();
        switch (this.ort){
            case Orientation.UP:
                if(ort==Orientation.DOWN) {
                    left_up.setY(left_up.getY() + 10);
                    if(!canMove())
                        left_up.setY(left_up.getY() -10);
                    else
                        this.ort=ort;
                }
                if(ort==Orientation.LEFT){
                    left_up.setY(left_up.getY()+10);
                    left_up.setX(left_up.getX()-10);
                    swapWidAndHei();
                    if(!canMove())
                    {
                        left_up.setY(left_up.getY()-10);
                        left_up.setX(left_up.getX()+10);
                        swapWidAndHei();
                    }
                    else
                        this.ort=ort;
                }
                if(ort==Orientation.RIGHT){
                    swapWidAndHei();
                    left_up.setY(left_up.getY() + 10);
                    if(!canMove()) {
                        left_up.setY(left_up.getY() - 10);
                        swapWidAndHei();
                    }
                    else
                        this.ort=ort;
                }
                break;
            case Orientation.DOWN:
                if(ort==Orientation.UP) {
                    left_up.setY(left_up.getY() -10);
                    if(!canMove())
                        left_up.setY(left_up.getY() +10);
                    else
                        this.ort=ort;
                }
                if(ort==Orientation.LEFT){
                    left_up.setX(left_up.getX()-10);
                    swapWidAndHei();
                    if(!canMove())
                    {
                        left_up.setX(left_up.getX()+10);
                        swapWidAndHei();
                    }
                    else
                        this.ort=ort;
                }
                if(ort==Orientation.RIGHT){
                    swapWidAndHei();
                    if (canMove())
                        this.ort=ort;
                    else
                        swapWidAndHei();
                }
                break;
            case Orientation.LEFT:
                if(ort==Orientation.DOWN) {
                    left_up.setX(left_up.getX()+10);
                    swapWidAndHei();
                    if(!canMove()) {
                        left_up.setX(left_up.getX() - 10);
                        swapWidAndHei();
                    }
                    else
                        this.ort=ort;
                }
                if(ort==Orientation.UP){
                    left_up.setY(left_up.getY()-10);
                    left_up.setX(left_up.getX()+10);
                    swapWidAndHei();
                    if(!canMove())
                    {
                        left_up.setY(left_up.getY()+10);
                        left_up.setX(left_up.getX()-10);
                        swapWidAndHei();
                    }
                    else
                        this.ort=ort;
                }
                if(ort==Orientation.RIGHT){
                    left_up.setX(left_up.getX()+10);
                    if(!canMove())
                        left_up.setX(left_up.getX()-10);
                    else
                        this.ort=ort;
                }
                break;
            case Orientation.RIGHT:
                if(ort==Orientation.DOWN) {
                    swapWidAndHei();
                    if (canMove())
                        this.ort=ort;
                    else
                        swapWidAndHei();
                }
                if(ort==Orientation.UP){
                    left_up.setY(left_up.getY()-10);
                    swapWidAndHei();
                    if(!canMove())
                    {
                        left_up.setY(left_up.getY()+10);
                        swapWidAndHei();
                    }
                    else
                        this.ort=ort;
                }
                if(ort==Orientation.LEFT){
                    left_up.setX(left_up.getX()-10);
                    if(!canMove())
                        left_up.setX(left_up.getX()+10);
                    else
                        this.ort=ort;
                }
                break;
            default:break;
        }
        rwLock.writeLock().unlock();
    }

    @JsonSetter("ort")
    public void initOrt(int ort){
        this.ort=ort;
    }
    private void swapWidAndHei() {
        int width=getWidth();
        setWidth(getHeight());
        setHeight(width);
    }

    public ObjectManager getManager() {
        return manager;
    }

    public BaseTank setManager(ObjectManager manager) {
        this.manager = manager;
        return this;
    }

    @Override
    public void setAlive(boolean alive) {
        super.setAlive(alive);
        if(!alive) {
            manager.addBomb(new Bomb(this));
            timer1.End();
        }
    }

    @Override
    public  void draw(Graphics g) {
       if(manager==null)
           return;
       if(isAlive==false)
           return;
       //避免绘制尝试移动时的坦克
        rwLock.readLock().lock();
        g.setColor(getBackColor());
        switch (ort){
            case Orientation.UP:
                //左轮
                g.fill3DRect(getLeft_up().getX(),getLeft_up().getY()+10,10,40, true);
                //枪管
                g.fill3DRect(getLeft_up().getX()+17,getLeft_up().getY(),6,30,true);
                //中室
                g.fill3DRect(getLeft_up().getX()+10,getLeft_up().getY()+20,20,20 ,true);
                //右轮
                g.fill3DRect(getLeft_up().getX()+30,getLeft_up().getY()+10,10,40, true);
                break;
            case Orientation.DOWN:
                //左轮
                g.fill3DRect(getLeft_up().getX(),getLeft_up().getY(),10,40, true);
                //枪管
                g.fill3DRect(getLeft_up().getX()+17,getLeft_up().getY()+20,6,30,true);
                //中室
                g.fill3DRect(getLeft_up().getX()+10,getLeft_up().getY()+10,20,20 ,true);
                //右轮
                g.fill3DRect(getLeft_up().getX()+30,getLeft_up().getY(),10,40, true);break;
            case Orientation.LEFT:
                //左轮
                g.fill3DRect(getLeft_up().getX()+10,getLeft_up().getY(),40,10, true);
                //枪管
                g.fill3DRect(getLeft_up().getX(),getLeft_up().getY()+17,30,6,true);
                //中室
                g.fill3DRect(getLeft_up().getX()+20,getLeft_up().getY()+10,20,20 ,true);
                //右轮
                g.fill3DRect(getLeft_up().getX()+10,getLeft_up().getY()+30,40,10, true);break;
            case Orientation.RIGHT:
                //左轮
                g.fill3DRect(getLeft_up().getX(),getLeft_up().getY(),40,10, true);
                //枪管
                g.fill3DRect(getLeft_up().getX()+20,getLeft_up().getY()+17,30,6,true);
                //中室
                g.fill3DRect(getLeft_up().getX()+10,getLeft_up().getY()+10,20,20 ,true);
                //右轮
                g.fill3DRect(getLeft_up().getX(),getLeft_up().getY()+30,40,10, true);break;
            default:break;
        }
        rwLock.readLock().unlock();
    }

    @Override
    public boolean canMove() {
        //检查是否到边界
        if (left_up.getX() < 0 || left_up.getY() < 0 || getRight_down().getX() > manager.getGamePanel().getWidth() ||getRight_down().getY() > manager.getGamePanel().getHeight())
            return false;
        //检查是否与其它坦克重叠
        if (manager.getMyTank().isAlive() &&this != manager.getMyTank()&&this.isIntersect(manager.getMyTank()))
            return false;
        for(int i=0;i<manager.getEnemyTanks().size();i++) {
            EnemyTank tank=manager.getEnemyTanks().get(i);
            if (tank.isAlive() && this.isIntersect(tank) && this != tank)
                return false;
        }
        for(int i=0;i<manager.getBarriers().size();i++) {
            Barrier barrier=manager.getBarriers().get(i);
            if (barrier.isIntersect(this))
                return false;
        }
        return true;
    }

    @Override
    public boolean move() {
        boolean result = true;
        switch (ort) {
            case Orientation.UP:
                for (int i = 0; i < speed; i++) {
                    rwLock.writeLock().lock();
                    left_up.setY(left_up.getY() - 1);
                    if (!canMove()) {
                        left_up.setY(left_up.getY() + 1);
                        result = false;
                    }
                    rwLock.writeLock().unlock();
                }
                break;
            case Orientation.DOWN:
                for (int i = 0; i < speed; i++) {
                    rwLock.writeLock().lock();
                    left_up.setY(left_up.getY() + 1);
                    if (!canMove()) {
                        left_up.setY(left_up.getY() - 1);
                        result = false;
                    }
                    rwLock.writeLock().unlock();
                }
                break;
            case Orientation.LEFT:
                for (int i = 0; i < speed; i++) {
                    rwLock.writeLock().lock();
                    left_up.setX(left_up.getX() - 1);
                    if (!canMove()) {
                        left_up.setX(left_up.getX() + 1);
                        result = false;
                    }
                    rwLock.writeLock().unlock();
                }
                break;
            case Orientation.RIGHT:
                for (int i = 0; i < speed; i++) {
                    rwLock.writeLock().lock();
                    left_up.setX(left_up.getX() + 1);
                    if (!canMove()) {
                        left_up.setX(left_up.getX() - 1);
                        result = false;
                    }
                    rwLock.writeLock().unlock();
                }
                break;
            default:
                break;
        }
        return result;
    }

    public void shitBullet(){
        if(timer1.isOverOne()) {
            Bullet bullet = new Bullet(this);
            manager.addBullet(bullet);
            bullet.start();
            timer1.Start();
        }
    }
}
